package com.itggm.service.impl;


import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itggm.Result.ResponseResult;
import com.itggm.dto.*;
import com.itggm.exception.BusinessException;
import com.itggm.mapper.*;
import com.itggm.pojo.Permission;
import com.itggm.pojo.RolePermission;
import com.itggm.pojo.User;
import com.itggm.pojo.UserRole;
import com.itggm.service.UserService;
import com.itggm.utils.IpUtil;
import com.itggm.utils.JWTUtil;
import com.itggm.vo.UserVO;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * @author root
 * @description 针对表【sys_user】的数据库操作Service实现
 * @createDate 2024-12-18 09:43:17
 */
@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private JWTUtil jwtUtil;
    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private RolePermissionMapper rolePermissionMapper;

    @Override
    public ResponseResult login(UserLoginDTO userLoginDTO, HttpServletRequest request) {
        //比较验证码
        String fromCode = userLoginDTO.getCode();
        String uuid = userLoginDTO.getUuid();
        String redisCode = stringRedisTemplate.opsForValue().get(uuid);
        if (ObjectUtils.isEmpty(redisCode)) {
            return ResponseResult.fail().message("验证码已失效请重新获取");
        }
        if (Double.parseDouble(fromCode) != Double.parseDouble(redisCode)) {
            return ResponseResult.fail().message("验证码错误，请重新输入");
        }
        //比较用户名和密码
        String username =userLoginDTO.getUsername();
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(User::getUsername, username);
        User user = baseMapper.selectOne(userLambdaQueryWrapper);
        if (ObjectUtils.isEmpty(user)) {
            return ResponseResult.fail().message("用户名不正确");
        }
        String formPassWord = userLoginDTO.getPassword();
        String DBPassWord = user.getPassword();
        String salt = user.getSalt();
        //加密前端表单传过来的密码
        String md5PassWord = new SimpleHash("MD5", formPassWord, salt, 10).toHex();
        //比较加密后的密码
        if (!DBPassWord.equals(md5PassWord)) {
            return ResponseResult.fail().message("密码不正确");
        }
        HashMap<String, Object> tokenMap = new HashMap<>();
        tokenMap.put("username", user.getUsername());
        tokenMap.put("id", user.getId());
        tokenMap.put("nickName", user.getNickName());
        String token = jwtUtil.createToken("UserInfo", tokenMap);
        System.out.println("token"+token);

        // 存储token   便于后续的状态判定
        String ip = IpUtil.getIp(request);
        stringRedisTemplate.opsForValue().set(token, ip);

        return ResponseResult.success()
                .message("认证通过")
                .data("token", token)
                .data("nickName", user.getNickName());
    }

    @Override
    public ResponseResult getPersonalInfo(String token) {
        //获取个人信息
        Map<String, Object> tokenMap = jwtUtil.analyzingToken("UserInfo", token);
        Integer id = (Integer) tokenMap.get("id");
        //根据id查询数据库信息
        User user = baseMapper.selectById(id);
        return ResponseResult.success().data("personal", user);
    }

    @Override
    public ResponseResult editPersonalInfo(EditPersonalInfoDTO editPersonalInfoDTO) {
        //编辑个人信息
        //比较验证码验,证码正确则修改
        String fromCode = editPersonalInfoDTO.getCode();
        //从redis获得验证码
        String email = editPersonalInfoDTO.getEmail();
        String redisCode = stringRedisTemplate.opsForValue().get(email);
        if (redisCode == null) {
            return ResponseResult.fail().message("验证码过期请重新获取");
        }
        if (!fromCode.equals(redisCode)) {
            return ResponseResult.fail().message("验证码不正确，请重新输入");
        }
        //修改数据库信息
        User user = new User();
        BeanUtils.copyProperties(editPersonalInfoDTO, user);
        baseMapper.updateById(user);
        return ResponseResult.success().message("操作成功");


    }

    @Override
    public ResponseResult editPersonalPwd(String token, EditPersonalPwdDTO editPersonalPwdDTO) {
        //先获取旧密码跟前端传过来的密码比较
        Map<String, Object> tokenMap = jwtUtil.analyzingToken("UserInfo", token);
        Integer id = (Integer) tokenMap.get("id");
        User user = baseMapper.selectById(id);
        String salt = user.getSalt();
        String oldDBPassword = user.getPassword();
        String oldFromPassword = editPersonalPwdDTO.getOldPassword();
        //对表单的密码进行加盐加密
        String md5PassWord = new SimpleHash("MD5", oldFromPassword, salt, 10).toHex();
        if (!md5PassWord.equals(oldDBPassword)) {
            return ResponseResult.fail().message("旧密码错误，请重新输入");
        }
        //如果密码一致则修改密码
        String newFromPassword = editPersonalPwdDTO.getNewPassword();
        String newMd5Password = new SimpleHash("MD5", newFromPassword, salt, 10).toHex();
        user.setPassword(newMd5Password);
        baseMapper.updateById(user);
        return ResponseResult.success().message("操作成功");

    }

    @Override
    public ResponseResult logout(String token) {
        stringRedisTemplate.delete(token);
        return ResponseResult.success();
    }

    @Override
    public ResponseResult userPage(UserPageDTO userPageDTO) {
        Integer page = userPageDTO.getPage();
        Integer limit = userPageDTO.getLimit();

        // 获取搜索条件
        String username = userPageDTO.getUsername();
        Integer deptId = userPageDTO.getDeptId();
        Integer state = userPageDTO.getState();

        // 创建动态条件构造器
        LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda();
        lambda.like(StringUtils.isNotBlank(username), User::getUsername, username)
                .eq(ObjectUtils.isNotNull(deptId), User::getDeptId, deptId)
                .eq(ObjectUtils.isNotNull(state), User::getState, state);

        // 创建分页对象
        Page<User> userPage = new Page<>(page, limit);
        baseMapper.selectPage(userPage, lambda);

        // 获取分页数据
        long total = userPage.getTotal();
        List<User> users = userPage.getRecords();
        // user   ->  userVO
        List<UserVO> userVOS = users.stream().map(user -> {
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(user, userVO);

            //  部门名称
            String deptName = deptMapper.selectById(user.getDeptId()).getDeptName();
            userVO.setDeptName(deptName);
            // 角色名称列表
            LambdaQueryWrapper<UserRole> lambda1 = new QueryWrapper<UserRole>().lambda();
            lambda1.eq(UserRole::getUserId, user.getId());
            List<Integer> rids = userRoleMapper.selectList(lambda1).stream()
                    .map(ur -> ur.getRoleId())
                    .collect(Collectors.toList());
            //设置用户角色
            userVO.setRoleId(rids);

            List<String> roleNames = roleMapper.selectByIds(rids).stream()
                    .map(role -> role.getRoleCh())
                    .collect(Collectors.toList());
            userVO.setRoleNames(roleNames);

            return userVO;
        }).collect(Collectors.toList());

        return ResponseResult.success()
                .data("total", total)
                .data("tableData", userVOS);
    }

    @Override
    public ResponseResult addUser(UserDTO userDTO) {
        //添加用户 user
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
        // 数据库中用户名字段是唯一索引  用户名重复 则抛出异常
        // 设置默认密码为123456
        String password = "123456";
        //生成一个随机盐
        String salt = RandomUtil.randomString(8);
        //进行哈希加密
        String md5Password = String.valueOf(new SimpleHash("MD5", password, salt, 10));
        user.setPassword(md5Password);
        user.setSalt(salt);
        user.setCreateTime(DateTime.now());

        //添加用户
        try {
            baseMapper.insert(user);
        } catch (DuplicateKeyException e) {
            throw new BusinessException("用户名已存在");
        }

        //添加用户角色 user_role
        Integer userId = user.getId();
        List<Integer> roleIds = userDTO.getRoleId();
        for (Integer roleId : roleIds) {
            UserRole userRole = new UserRole();
            userRole.setUserId(userId);
            userRole.setRoleId(roleId);
            userRoleMapper.insert(userRole);
        }
        return ResponseResult.success();


    }

    @Override
    public ResponseResult editUser(UserDTO userDTO) {
        //编辑用户
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
        baseMapper.updateById(user);
        //先删除user_role表
        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRole::getUserId, user.getId());
        userRoleMapper.delete(queryWrapper);
        //在添加user_role表
        List<Integer> roleId = userDTO.getRoleId();
        for (Integer id : roleId) {
            UserRole userRole = new UserRole();
            userRole.setRoleId(id);
            userRole.setUserId(user.getId());
            userRoleMapper.insert(userRole);
        }
        return ResponseResult.success();
    }

    @Override
    public ResponseResult deleteUsers(String ids) {
        String[] split = ids.split(",");
        List<Integer> uIds = JSONUtil.toList(JSONUtil.toJsonStr(split), Integer.class);
        //只能删除禁用状态的用户
        for (Integer uId : uIds) {
            User user = baseMapper.selectById(uId);
            if (user.getState() == 1) {
                return ResponseResult.fail().message("请先禁用账号再删除");
            } else {
                // 根据用户id  删除用户信息
                baseMapper.deleteById(uId);
                //  删除用户关联的角色信息   user_role
                LambdaQueryWrapper<UserRole> lambda = new QueryWrapper<UserRole>().lambda();
                lambda.in(UserRole::getUserId, uIds);
                userRoleMapper.delete(lambda);
            }
        }
        return ResponseResult.success();
    }

    @Override
    public ResponseResult resetPassword(Integer id) {
        //默认密码为123456
        // 设置默认密码为123456
        String password = "123456";
        //生成一个随机盐
        String salt = RandomUtil.randomString(8);
        //进行哈希加密
        String md5Password = String.valueOf(new SimpleHash("MD5", password, salt, 10));
        //根据id查询用户
        User user = baseMapper.selectById(id);
        user.setPassword(md5Password);
        user.setSalt(salt);
        //更新用户密码
        baseMapper.updateById(user);
        return ResponseResult.success();
    }

    @Override
    public ResponseResult changeUserState(UserStateDTO userStateDTO) {
        //改变用户账号状态
        //TODO 不能禁用在线用户的账号状态
        User user = new User();
        user.setState(userStateDTO.getState());
        user.setId(userStateDTO.getUid());
        baseMapper.updateById(user);
        return ResponseResult.success();


    }

    @Override
    public ResponseResult getUserMenu(String token) {
        Map<String, Object> tokenMap = jwtUtil.analyzingToken("UserInfo", token);
        Integer id = (Integer) tokenMap.get("id");
        LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserRole::getUserId,id);
        //根据userId查询roleId
        List<Integer> roleIds = userRoleMapper.selectList(queryWrapper)
                .stream().map(ur -> ur.getRoleId()).collect(Collectors.toList());
        //根据roleId查询pid
        LambdaQueryWrapper<RolePermission>  wrapper = new LambdaQueryWrapper<>();
        wrapper.in(RolePermission::getRoleId,roleIds);
        Set<Integer> pIds = rolePermissionMapper.selectList(wrapper)
                .stream().map(rolePermission -> rolePermission.getPerId()).collect(Collectors.toSet());
        //根据pIds查询权限列表
        LambdaQueryWrapper<Permission> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.in(Permission::getId,pIds).ne(Permission::getIsMenu,2);
        List<Permission> permissions = permissionMapper.selectList(queryWrapper1);


        return ResponseResult.success().data("DBPermissions",permissions);
    }


}




